package com.distribuida.supertrunfo.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import com.distribuida.supertrunfo.comum.Caracteristica;
import com.distribuida.supertrunfo.comum.Carta;
import com.distribuida.supertrunfo.comum.Jogador;
import com.distribuida.supertrunfo.comum.Opcoes;

class CaracteristicaJogador implements Comparable<CaracteristicaJogador> {
    private Jogador jogador;
    private Caracteristica caracteristica;
    
    public CaracteristicaJogador(Jogador jogador, Caracteristica caracteristica) {
        this.jogador = jogador;
        this.caracteristica = caracteristica;
    }
    
    public Jogador getJogador() {
        return jogador;
    }
    public void setJogador(Jogador jogador) {
        this.jogador = jogador;
    }
    
    public Caracteristica getCaracteristica() {
        return caracteristica;
    }
    public void setCaracteristica(Caracteristica caracteristica) {
        this.caracteristica = caracteristica;
    }
    
    @Override
    public int compareTo(CaracteristicaJogador caracteristicaJogador) {
        return this.caracteristica.compareTo(caracteristicaJogador.getCaracteristica()) * -1;
    }
}

public class Jogo {
    
    private ArrayList<Jogador> jogadores;
    private ArrayList<Jogador> vencedorRodada;
    private SuperTrunfo superTurnfo;
    private int rodada;
    private String idCaracteristica;
    private int id;
    private long ultimaJogada;
    private int idJogadorRodada;
    private boolean jogoEmAndamento;
    private HashMap<Integer, Opcoes> operacoesJogador;
    
    public Jogo(SuperTrunfo superTrunfo) {
        this.jogadores = new ArrayList<Jogador>(4);
        this.vencedorRodada = new ArrayList<Jogador>(4);
        this.superTurnfo = superTrunfo;
        this.rodada = 0;
        this.idCaracteristica = "";
        this.id = (int) System.nanoTime();
        this.ultimaJogada = System.currentTimeMillis();
        this.idJogadorRodada = 0;
        this.jogoEmAndamento = false;
    }
    
    public boolean removerJogador(int id){
        Jogador jog = null;
        for(Jogador jo: jogadores){
            if(jo.getId() == id){
                jog = jo;
            }
        }
        return jogadores.remove(jog);
    }
    
    public void distribuirCartas() {
        if(this.jogadores.size() == 3){
            superTurnfo.getCartas().remove(superTurnfo.getCartaByID("D7"));
            superTurnfo.getCartas().remove(superTurnfo.getCartaByID("D8"));
        }
        this.setJogoEmAndamento(true);
        //Collections.sort(superTurnfo.getCartas());
        //Collections.shuffle(superTurnfo.getCartas());
        
        for(int k=0; k<superTurnfo.getCartas().size();) {
            for(Jogador jogador : jogadores) {
                jogador.addCarta(superTurnfo.getCartas().get(k++));
            }
        }
        System.out.println("\n-----------------------------------");
        System.out.println("\nIniciando Partida: " + this.getRodada() + " do jogo: " + this.getId());
        System.out.println("\n-----------------------------------");
    }
    
    public void turno() {
        
        pontuacao(vencedor(obterCaracteristicaTurno()));
        System.out.println("\n-----------------------------------");
        System.out.println("\nRodada: " + this.getRodada() + " do jogo: " + this.getId());
        System.out.println("\n-----------------------------------");
        rodada++;
    }
    
    public Jogador getJogadorRodada(){
        return jogadores.get(idJogadorRodada);
    }
    
    public int getIdJogadorRodada() {
        return idJogadorRodada;
    }
    
    public void setIdJogadorRodada(int idJogadorRodada) {
        this.idJogadorRodada = idJogadorRodada;
    }
    
    public ArrayList<Jogador> getVencedor(){
        ArrayList<Jogador> vencedores = jogadores;
        Collections.sort(vencedores);
        for(int k=0; k<vencedores.size(); k++) {
            if(vencedores.get(0).getVitorias()!=vencedores.get(k).getVitorias()){
                vencedores.remove(k);
            }
        }
        return vencedores;
    }
    
    public ArrayList<CaracteristicaJogador> obterCaracteristicaTurno() {
        ArrayList<CaracteristicaJogador> retorno = new ArrayList<CaracteristicaJogador>();
        for(Jogador jog : jogadores){
            retorno.add(new CaracteristicaJogador(jog, jog.getCartas().get(rodada).getCaracteristicas().get(Integer.parseInt(idCaracteristica))));
        }
        Collections.sort(retorno);
        return retorno;
    }
    
    public ArrayList<Jogador> vencedor(ArrayList<CaracteristicaJogador> caracteristicas) {
        Jogador jogadorTrunfo = null;
        ArrayList<Jogador> venceTrunfo = new ArrayList<Jogador>();
        ArrayList<Jogador> vencedores = new ArrayList<Jogador>();
        vencedorRodada.clear();
        
        for (Jogador jogador : jogadores) {
            if(jogador.getCartas().get(rodada).isTrunfo()) {
                jogadorTrunfo = jogador;
            } else if(jogador.getCartas().get(rodada).isVencetrunfo()) {
                venceTrunfo.add(jogador);
            }
        }
        
        if(jogadorTrunfo != null && venceTrunfo.isEmpty()) {
            vencedores.add(jogadorTrunfo);
            vencedorRodada.addAll(vencedores);
            return vencedores;
        } else if (jogadorTrunfo != null && !venceTrunfo.isEmpty()) {
            vencedorRodada.addAll(venceTrunfo);
            return venceTrunfo;
        }
        
        Caracteristica caracteristicaAnterior = null;
        for (CaracteristicaJogador caracteristicaJogador : caracteristicas) {
            if (caracteristicaAnterior == null) {
                caracteristicaAnterior = caracteristicaJogador.getCaracteristica();
                vencedores.add(caracteristicaJogador.getJogador());
            } else if (caracteristicaAnterior.compareTo(caracteristicaJogador.getCaracteristica()) == 0) {
                vencedores.add(caracteristicaJogador.getJogador());
            } else {
                break;
            }
        }
        
        vencedorRodada.addAll(vencedores);
        return vencedores;
    }
    
    public void pontuacao(ArrayList<Jogador> vencedores) {
        for (Jogador vencedor : vencedores) {
            vencedor.setVitorias(vencedor.getVitorias() + jogadores.size() - vencedores.size());
            System.out.print("Vitorias do Jogador: " + vencedor.getNome() + " - " + vencedor.getVitorias());
        }
    }
    
    public boolean adicionarJogador(Jogador jogador) throws Exception{
        if(jogadores.size() == 4){
            throw new Exception("Numero maximo de Jogadores por jogo alcancado");
        }
        jogador.setId_jogo(id);
        return jogadores.add(jogador);
    }
    
    public Carta retornaCartaRodada(int id_jogador){
        for(Jogador jog : jogadores){
            if(jog.getId() == id_jogador){
                if(jog.getCartas().get(rodada) != null)
                    return jog.getCartas().get(rodada);
            }
        }
        return null;
    }
    
    public void setOperacaoJogador(int id_jogador, Opcoes opcao){
        operacoesJogador.put(id_jogador, opcao);
    }
    
    public ArrayList<Jogador> getJogadores() {
        return jogadores;
    }
    
    public SuperTrunfo getSuperTurnfo() {
        return superTurnfo;
    }
    
    public int getRodada() {
        return rodada;
    }
    
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    
    public long getUltimaJogada() {
        return ultimaJogada;
    }
    public void setUltimaJogada(long ultimaJogada) {
        this.ultimaJogada = ultimaJogada;
    }
    
    public String getIdCaracteristica() {
        return idCaracteristica;
    }
    public void setIdCaracteristica(String idCaracteristica) {
        this.idCaracteristica = idCaracteristica;
        if(rodada == 0){
            distribuirCartas();
        }
    }
    
    public ArrayList<Jogador> getVencedorRodada() {
        return vencedorRodada;
    }
    
    public void setVencedorRodada(ArrayList<Jogador> vencedorRodada) {
        this.vencedorRodada = vencedorRodada;
    }
    
    public HashMap<Integer, Opcoes> getOperacoesJogador() {
        return operacoesJogador;
    }
    
    public void setOperacoesJogador(HashMap<Integer, Opcoes> operacoesJogador) {
        this.operacoesJogador = operacoesJogador;
    }
    
    public boolean isJogoEmAndamento() {
        return jogoEmAndamento;
    }
    
    public void setJogoEmAndamento(boolean jogoEmAndamento) {
        this.jogoEmAndamento = jogoEmAndamento;
    }
    
}